home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
DCLAP 6d
/
dclap6d
/
corelib
/
ncbibs.c
< prev
next >
Wrap
Text File
|
1996-07-05
|
21KB
|
809 lines
/* ncbibs.c
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
* National Center for Biotechnology Information
*
* This software/database is a "United States Government Work" under the
* terms of the United States Copyright Act. It was written as part of
* the author's official duties as a United States Government employee and
* thus cannot be copyrighted. This software/database is freely available
* to the public for use. The National Library of Medicine and the U.S.
* Government have not placed any restriction on its use or reproduction.
*
* Although all reasonable efforts have been taken to ensure the accuracy
* and reliability of the software and data, the NLM and the U.S.
* Government do not and cannot warrant the performance or results that
* may be obtained by using this software or data. The NLM and the U.S.
* Government disclaim all warranties, express or implied, including
* warranties of performance, merchantability or fitness for any particular
* purpose.
*
* Please cite the author in any work or product based on this material.
*
* ===========================================================================
*
* File Name: ncbibs.c
*
* Author: Jim Ostell
*
* Version Creation Date: 3/4/91
*
* $Revision: 2.7 $
*
* File Description:
* ByteStore functions
* NOTE: increasing BS_MAXALLOC will require changing len, and
* len_avail to Int4 (ncbibs.h)
*
* This version needs the following enhancements:
* 1) a BSCompact function to pack a fragmented ByteStore
* 2) use made of MIN_BSALLOC to make all allocated space at
* least MIN_BSALLOC long, so it would be possible to have len_avail
* bigger than len at internal BSUnits as well as at the end. This
* will make insertion and appending of small amounts much more
* efficient.
*
* Modifications:
* --------------------------------------------------------------------------
* Date Name Description of modification
* ------- ---------- -----------------------------------------------------
* 3/4/91 Kans Stricter typecasting for GNU C and C++.
* 09-19-91 Schuler All sizes are expressed as Int4, not Uint4.
* 09-20-91 Schuler All exported functions are LIBCALL.
* 09-20-91 Schuler BSGetByte returns EOF on failure.
* 09-20-91 Schuler BSPutByte(bsp,EOF) truncates bsp at curr. position.
* 04-15-93 Schuler Changed _cdecl to LIBCALL
*
* ==========================================================================
*/
#include <ncbi.h>
#include <ncbiwin.h>
/* maximum size allocated for BSUnit.str */
#define MAX_BSALLOC 32700
/* minimum size block to allocate except on new */
#define MIN_BSALLOC 1024
#ifdef MSC_VIRT
extern Nlm_Boolean wrote_to_handle; /* needed by Microsoft DOS Virtual mem */
#undef MAX_BSALLOC /* bad with big blocks */
#define MAX_BSALLOC 10000
#endif
/*****************************************************************************
*
* Pointer Nlm_BSMerge(bsp, dest)
* if dest == NULL, allocates storage for merge and returns pointer to it
*
*****************************************************************************/
Nlm_VoidPtr LIBCALL Nlm_BSMerge (Nlm_ByteStorePtr bsp, Nlm_VoidPtr dest)
{
Nlm_BytePtr tmp, from;
Nlm_BSUnitPtr bsup;
Nlm_Int4 size;
if (bsp == NULL)
return NULL;
size = Nlm_BSLen(bsp) + 1;
if (size > SIZE_MAX) {
/* should post an error here */
return NULL;
}
if (dest == NULL) /* allocate storage with room for null at end */
{
dest = Nlm_MemNew((size_t) size);
if (dest == NULL) return dest;
}
tmp = (Nlm_BytePtr) dest;
bsup = bsp->chain;
while (bsup != NULL)
{
from = (Nlm_BytePtr) Nlm_HandLock(bsup->str);
Nlm_MemCopy(tmp, from, bsup->len);
Nlm_HandUnlock(bsup->str);
tmp += bsup->len;
bsup = bsup->next;
}
return dest;
}
/*****************************************************************************
*
* ByteStorePtr Nlm_BSNew(len)
* creates a big enough bytestore for len
*
*****************************************************************************/
Nlm_ByteStorePtr LIBCALL Nlm_BSNew (Nlm_Int4 len)
{
Nlm_ByteStorePtr bsp;
Nlm_Int4 added;
bsp = (Nlm_ByteStorePtr) Nlm_MemNew(sizeof(ByteStore));
if (bsp == NULL)
return NULL;
added = Nlm_BSAdd(bsp, len);
if (added < len)
bsp = Nlm_BSFree(bsp);
return bsp;
}
/*****************************************************************************
*
* Int4 BSAdd(bsp, len)
* adds len bytes BEFORE current bsp->seekptr
* bsp->seekptr returned pointing at first added byte
* returns bytes added
*
*****************************************************************************/
Nlm_Int4 LIBCALL Nlm_BSAdd (Nlm_ByteStorePtr bsp, Nlm_Int4 len)
{
Nlm_BSUnitPtr bsup, /* current bsunit */
ccbsup, /* bsp->curchain */
lastbsup, /* bsunit after added section */
prevbsup; /* bsunit before added section */
Nlm_BytePtr to, from;
Nlm_Int4 added = 0,
tlen;
Nlm_Handle thand;
if ((bsp == NULL) || (len == 0))
return added;
lastbsup = NULL;
prevbsup = NULL;
ccbsup = bsp->curchain;
if (bsp->chain != NULL) /* add or insert in exisiting chain */
{
if (bsp->seekptr == bsp->chain_offset) /* before start of block */
{
lastbsup = ccbsup; /* it comes after */
if (bsp->seekptr != 0) /* something before it */
{
prevbsup = bsp->chain;
while (prevbsup->next != ccbsup)
prevbsup = prevbsup->next;
}
} /* after all blocks */
else if (bsp->seekptr >= (bsp->chain_offset + ccbsup->len_avail))
{
prevbsup = ccbsup;
}
else /* split a bsunit */
{
bsup = (Nlm_BSUnitPtr) Nlm_MemNew(sizeof(Nlm_BSUnit));
if (bsup == NULL) return added;
if (bsp->chain_offset != 0) /* not first BSUnit */
{
prevbsup = bsp->chain;
while (prevbsup->next != ccbsup)
prevbsup = prevbsup->next;
prevbsup->next = bsup; /* insert new bsunit */
}
else
bsp->chain = bsup;
bsup->next = ccbsup;
tlen = bsp->seekptr - bsp->chain_offset; /* len of first half */
bsup->str = Nlm_HandNew((size_t) tlen);
if (bsup->str == NULL) return added;
bsup->len = (Nlm_Int2) tlen;
bsup->len_avail = (Nlm_Int2) tlen;
to = (Nlm_BytePtr) Nlm_HandLock(bsup->str);
thand = ccbsup->str;
from = (Nlm_BytePtr) Nlm_HandLock(thand);
Nlm_MemCopy(to, from, (size_t) tlen);
#ifdef MSC_VIRT
wrote_to_handle = TRUE;
#endif
Nlm_HandUnlock(bsup->str);
from += tlen; /* point past copied region */
tlen = ccbsup->len - tlen; /* the last half */
ccbsup->len = (Nlm_Int2) tlen;
ccbsup->len_avail = (Nlm_Int2) tlen;
ccbsup->str = Nlm_HandNew((size_t) tlen);
if (ccbsup->str == NULL) return added;
to = (Nlm_BytePtr) Nlm_HandLock(ccbsup->str);
Nlm_MemCopy(to, from, (size_t) tlen);
#ifdef MSC_VIRT
wrote_to_handle = TRUE;
#endif
Nlm_HandUnlock(ccbsup->str);
Nlm_HandUnlock(thand);
Nlm_HandFree(thand);
prevbsup = bsup;
lastbsup = ccbsup;
}
}
ccbsup = NULL;
bsup = NULL;
while (len)
{
bsup = (Nlm_BSUnitPtr) Nlm_MemNew(sizeof(Nlm_BSUnit));
if (bsup == NULL)
return added;
if (len < MAX_BSALLOC)
tlen = len;
else
tlen = MAX_BSALLOC;
bsup->str = Nlm_HandNew((size_t)tlen);
if (bsup->str == NULL)
{
Nlm_MemFree(bsup);
return added;
}
bsup->len_avail = (Nlm_Int2) tlen;
if (prevbsup == NULL)
bsp->chain = bsup;
else
prevbsup->next = bsup;
if (ccbsup == NULL)
ccbsup = bsup; /* current position */
prevbsup = bsup;
len -= tlen;
added += tlen;
}
if (bsup != NULL)
bsup->next = lastbsup;
bsp->curchain = ccbsup;
bsp->chain_offset = bsp->seekptr; /* added block starts at seekptr */
return added;
}
/*****************************************************************************
*
* Int4 BSDelete(bsp, len)
* deletes len bytes starting at current bsp->seekptr
* returns bytes deleted
*
*****************************************************************************/
Nlm_Int4 LIBCALL Nlm_BSDelete (Nlm_ByteStorePtr bsp, Nlm_Int4 len)
{
Nlm_BSUnitPtr bsup, /* current bsunit */
ccbsup, /* bsp->curchain */
nextbsup, /* bsunit after added section */
prevbsup; /* bsunit before added section */
Nlm_BytePtr to, from;
Nlm_Int4 added = 0,
offset,
tlen,
start,
save;
Nlm_Handle thand;
if ((bsp == NULL) || (len == 0) || (bsp->chain == NULL) ||
(bsp->seekptr >= bsp->totlen))
return added;
if ((bsp->seekptr + len) > bsp->totlen) /* deleting too much */
len = bsp->totlen - bsp->seekptr;
nextbsup = NULL;
ccbsup = bsp->curchain;
start = bsp->chain_offset;
offset = bsp->seekptr - bsp->chain_offset;
if (offset) /* will leave part of first bsunit */
prevbsup = ccbsup;
else if (bsp->chain_offset != 0) /* something before this bsunit */
{
prevbsup = bsp->chain;
while (prevbsup->next != ccbsup)
prevbsup = prevbsup->next;
}
else
prevbsup = NULL; /* will remove beginning of first bsunit */
bsup = ccbsup;
while (len)
{
nextbsup = bsup->next;
tlen = bsup->len - offset;
if (tlen > len)
tlen = len; /* will remove tlen bytes from this BSUnit*/
save = bsup->len - tlen;
if (save) /* some bytes left after delete */
{
thand = bsup->str;
bsup->str = Nlm_HandNew((size_t) save);
if (bsup->str == NULL) return added;
bsup->len = (Nlm_Int2) save;
bsup->len_avail = (Nlm_Int2) save;
to = (Nlm_BytePtr) Nlm_HandLock(bsup->str);
from = (Nlm_BytePtr) Nlm_HandLock(thand);
if (offset) /* get the beginning */
Nlm_MemCopy(to, from, (size_t) offset);
save -= offset;
if (save) /* save end */
Nlm_MemCopy((to + offset), (from + (offset + tlen)), (size_t)save);
Nlm_HandUnlock(thand);
Nlm_HandFree(thand);
#ifdef MSC_VIRT
wrote_to_handle = TRUE;
#endif
Nlm_HandUnlock(bsup->str);
if (tlen < len)
bsup = nextbsup;
}
else /* delete the whole thing */
{
Nlm_HandFree(bsup->str);
Nlm_MemFree(bsup);
bsup = nextbsup;
}
offset = 0;
len -= tlen;
added += tlen;
}
if (bsup != prevbsup) /* break in chain, rejoin it */
{
if (prevbsup == NULL)
bsp->chain = bsup;
else
prevbsup->next = bsup;
}
bsp->curchain = bsup;
bsp->totlen -= added;
if (bsp->totlen)
{
offset = bsp->seekptr;
start = 0;
bsup = bsp->chain;
while (offset >= (start + bsup->len_avail))
{
if (bsup->next == NULL) /* EOF */
offset = 0; /* stop loop */
else
{
start += bsup->len;
bsup = bsup->next;
}
}
bsp->curchain = bsup;
bsp->chain_offset = start;
}
else
{
bsp->chain_offset = 0;
bsp->curchain = bsp->chain;
}
return added;
}
/*****************************************************************************
*
* Nlm_Int4 Nlm_BSTell(bsp)
*
*****************************************************************************/
Nlm_Int4 LIBCALL Nlm_BSTell (Nlm_ByteStorePtr bsp)
{
if (bsp == NULL)
return 0L;
return bsp->seekptr;
}
/*****************************************************************************
*
* Int2 Nlm_BSSeek(bsp, offset, origin)
* seeks as fseek()
* trys to lock a BSUnit at that seek position
*
*****************************************************************************/
Nlm_Int2 LIBCALL Nlm_BSSeek (Nlm_ByteStorePtr bsp, Nlm_Int4 offset, Nlm_Int2 origin)
{
Nlm_Int4 sp, start;
Nlm_BSUnitPtr bsup;
Nlm_Boolean done;
if (bsp == NULL)
return 1;
if (bsp->chain == NULL)
return 1;
sp = bsp->seekptr;
switch (origin)
{
case SEEK_SET:
if ((offset > bsp->totlen) || (offset < 0))
return 1;
sp = offset;
break;
case SEEK_CUR:
if (((sp + offset) > bsp->totlen) ||
((sp + offset) < 0 ))
return 1;
sp += offset;
break;
case SEEK_END:
if ((ABS(offset) > bsp->totlen) || (offset > 0))
return 1;
sp = bsp->totlen + offset;
break;
default:
return 1;
}
if (sp == bsp->seekptr) /* already in right position */
return 0;
bsp->seekptr = sp;
/* if a valid seek, lock the right BSUnit */
bsup = bsp->curchain;
if (sp == bsp->totlen) /* seek to EOF */
{
if (sp > (bsp->chain_offset + bsup->len_avail))
{
start = bsp->chain_offset;
while (sp > (start + bsup->len_avail))
{
start += bsup->len;
bsup = bsup->next;
}
}
}
else if ((sp < bsp->chain_offset) ||
(sp >= (bsp->chain_offset + bsup->len)))
{
if (sp < bsp->chain_offset)
{
bsup = bsp->chain;
start = 0;
}
else
{
start = bsp->chain_offset + bsup->len;
bsup = bsup->next;
}
done = FALSE;
while (! done)
{
if ((start + bsup->len) > sp)
done = TRUE;
else
{
start += bsup->len;
bsup = bsup->next;
}
}
}
if (bsup != bsp->curchain)
{
bsp->chain_offset = start;
bsp->curchain = bsup;
}
return 0;
}
/*****************************************************************************
*
* Int4 Nlm_BSLen(bsp)
* gives cumulative length of strings in store (not counting \0)
*
*****************************************************************************/
Nlm_Int4 LIBCALL Nlm_BSLen (Nlm_ByteStorePtr bsp)
{
if (bsp == NULL)
return 0L;
return bsp->totlen;
}
/*****************************************************************************
*
* Int2 BSPutByte(bsp, value)
* - returns value on success, EOF on failure
* - BSPutByte(bsp, EOF) truncates at seekptr
*
*****************************************************************************/
Nlm_Int2 LIBCALL Nlm_BSPutByte (Nlm_ByteStorePtr bsp, Nlm_Int2 value)
{
Nlm_Uint1 b;
if (value == EOF)
Nlm_BSDelete(bsp, INT4_MAX);
else {
b = (Nlm_Uint1) value;
if (Nlm_BSWrite(bsp, (Nlm_VoidPtr)&b, 1) == 0)
return EOF;
}
return value;
}
/*****************************************************************************
*
* Int4 BSWrite(bsp, ptr, len)
* returns bytes written from ptr to bsp
* writes from current seekptr position
* seekptr left pointing after last byte written
* allocates storage if needed
* writes over any data already there
*
*****************************************************************************/
Nlm_Int4 LIBCALL Nlm_BSWrite (Nlm_ByteStorePtr bsp, Nlm_VoidPtr ptr, Nlm_Int4 len)
{
Nlm_BytePtr from, to;
Nlm_BSUnitPtr bsup;
Nlm_Int4 tlen, added = 0, offset, start, diff;
if ((bsp == NULL) || (len <= 0))
return added;
bsup = bsp->curchain;
from = (Nlm_BytePtr) ptr;
offset = bsp->seekptr - bsp->chain_offset;
start = bsp->chain_offset;
while (len)
{
if (bsup == NULL)
tlen = 0;
else
tlen = bsup->len_avail - offset;
if (len < tlen)
tlen = len;
if (! tlen) /* out of space */
{
Nlm_BSAdd(bsp, len);
bsup = bsp->curchain;
offset = bsp->seekptr - bsp->chain_offset;
tlen = bsup->len_avail;
}
else
{
bsp->chain_offset = start;
bsp->curchain = bsup;
}
to = (Nlm_BytePtr)Nlm_HandLock(bsup->str) + offset;
Nlm_MemCopy(to, from, (size_t) tlen);
#ifdef MSC_VIRT
wrote_to_handle = TRUE;
#endif
Nlm_HandUnlock(bsup->str);
if (bsup->len < (Nlm_Int2)(tlen + offset)) /* added more to this bsunit */
{
diff = (tlen + offset) - bsup->len;
bsp->totlen += diff;
bsup->len += (Nlm_Int2) diff;
}
offset = 0; /* only offset on first one */
len -= tlen;
bsp->seekptr += tlen;
start += bsup->len;
added += tlen;
from += tlen;
if (len)
bsup = bsup->next;
}
/* pointing past end of this BSunit */
if ((bsp->seekptr - bsp->chain_offset) >= bsup->len_avail)
{
if (bsup->next != NULL) /* not end of space */
{
bsp->curchain = bsup->next;
bsp->chain_offset += bsup->len; /* should = len_avail */
}
}
return added;
}
/*****************************************************************************
*
* Int4 BSRead(bsp, ptr, len)
* returns bytes read from bsp to ptr
* reads from current seekptr position
* seekptr left pointing after last byte read
*
*****************************************************************************/
Nlm_Int4 LIBCALL Nlm_BSRead (Nlm_ByteStorePtr bsp, Nlm_VoidPtr ptr, Nlm_Int4 len)
{
Nlm_BytePtr from, to;
Nlm_BSUnitPtr bsup;
Nlm_Int4 tlen, added = 0, offset, start;
if ((bsp == NULL) || (len <= 0))
return added;
bsup = bsp->curchain;
to = (Nlm_BytePtr) ptr;
offset = bsp->seekptr - bsp->chain_offset;
start = bsp->chain_offset;
while (len)
{
if (bsup == NULL)
return added;
tlen = bsup->len - offset;
if (len < tlen)
tlen = len;
if (! tlen) /* out of data */
return added;
bsp->chain_offset = start;
from = (Nlm_BytePtr)Nlm_HandLock(bsup->str) + offset;
Nlm_MemCopy(to, from, (size_t) tlen);
Nlm_HandUnlock(bsup->str);
offset = 0; /* only offset on first one */
len -= tlen;
bsp->seekptr += tlen;
bsp->curchain = bsup;
start += bsup->len;
added += tlen;
to += tlen;
if (len)
bsup = bsup->next;
} /*** end of this bsunit? **/
if ((bsp->seekptr - bsp->chain_offset) == bsup->len)
{
if (bsp->seekptr != bsp->totlen) /* not EOF */
{
bsp->curchain = bsup->next;
bsp->chain_offset += bsup->len;
}
}
return added;
}
/*****************************************************************************
*
* Int2 BSGetByte(bsp)
* reads a byte and increments the seekptr
* returns EOF on End-Of-BS or error
*
*****************************************************************************/
Nlm_Int2 LIBCALL Nlm_BSGetByte (Nlm_ByteStorePtr bsp)
{
Nlm_Int2 retval;
Nlm_BytePtr ptr;
Nlm_Int4 diff;
Nlm_BSUnitPtr bsup;
if ((bsp == NULL) || (bsp->totlen == 0) || (bsp->seekptr == bsp->totlen))
return EOF; /* EOF */
diff = bsp->seekptr - bsp->chain_offset;
bsup = bsp->curchain;
ptr = (Nlm_BytePtr) Nlm_HandLock(bsup->str);
retval = (Nlm_Int2) *(ptr + diff);
Nlm_HandUnlock(bsup->str);
bsp->seekptr++;
diff++;
if (diff == bsup->len)
{
if (bsp->seekptr != bsp->totlen) /* not EOF */
{
bsp->curchain = bsup->next;
bsp->chain_offset += bsup->len;
}
}
return retval;
}
/*****************************************************************************
*
* Int4 BSInsert(bsp, ptr, len)
* returns bytes written from ptr into bsp
* writes from current seekptr position
* seekptr left pointing after last byte written
* allocates storage if needed
* inserts data BEFORE seekptr
*
*****************************************************************************/
Nlm_Int4 LIBCALL Nlm_BSInsert (Nlm_ByteStorePtr bsp, Nlm_VoidPtr ptr, Nlm_Int4 len)
{
Nlm_Int4 added;
added = Nlm_BSAdd(bsp, len);
if (added != len)
{
Nlm_BSDelete(bsp, added);
return 0;
}
added = Nlm_BSWrite(bsp, ptr, len);
return added;
}
/*****************************************************************************
*
* Int4 BSInsertFromBS(bsp, bsp2, len)
* returns bytes written from bsp2 into bsp
* reads from bsp2 starting from current seek position
* writes from current seekptr position
* seekptr left pointing after last byte written
* allocates storage if needed
* inserts data BEFORE seekptr
*
*****************************************************************************/
Nlm_Int4 LIBCALL Nlm_BSInsertFromBS (Nlm_ByteStorePtr bsp, Nlm_ByteStorePtr bsp2, Nlm_Int4 len)
{
Nlm_Int4 added;
Nlm_Int2 x;
added = Nlm_BSAdd(bsp, len);
if (added != len)
{
Nlm_BSDelete(bsp, added);
return 0;
}
for (added = 0; added < len; added++)
{
x = Nlm_BSGetByte(bsp2);
Nlm_BSPutByte(bsp, x);
}
return added;
}
/*****************************************************************************
*
* ByteStorePtr Nlm_BSFree(bsp)
*
*****************************************************************************/
Nlm_ByteStorePtr LIBCALL Nlm_BSFree (Nlm_ByteStorePtr bsp)
{
Nlm_BSUnitPtr bsup, tmp;
if (bsp == NULL)
return NULL;
bsup = bsp->chain;
while (bsup != NULL)
{
tmp = bsup;
bsup = bsup->next;
Nlm_HandFree(tmp->str);
Nlm_MemFree(tmp);
}
return (Nlm_ByteStorePtr) Nlm_MemFree(bsp);
}
Nlm_ByteStorePtr LIBCALL Nlm_BSDup(Nlm_ByteStorePtr source)
{
Nlm_ByteStorePtr dest;
Nlm_Int4 sourceLen;
Nlm_Int4 sourceLoc;
Nlm_Int4 added;
if (source == NULL)
{
return NULL;
}
sourceLen = Nlm_BSLen(source);
dest = Nlm_BSNew(0);
/* read the original location */
sourceLoc = Nlm_BSTell(source);
Nlm_BSSeek(source, 0, SEEK_SET);
added = Nlm_BSInsertFromBS(dest, source, sourceLen);
/* restore original location */
Nlm_BSSeek(source, sourceLoc, SEEK_SET);
if (added != sourceLen)
{
Nlm_BSFree(dest);
return NULL;
}
/* for neatness, make the duplicate point to the same location as the
old one */
Nlm_BSSeek(dest, sourceLoc, SEEK_SET);
return dest;
}